package com.qianfeng.smartplatform.config;

//
//                            _ooOoo_  
//                           o8888888o  
//                           88" . "88  
//                           (| -_- |)  
//                            O\ = /O  
//                        ____/`---'\____  
//                      .   ' \\| |// `.  
//                       / \\||| : |||// \  
//                     / _||||| -:- |||||- \  
//                       | | \\\ - /// | |  
//                     | \_| ''\---/'' | |  
//                      \ .-\__ `-` ___/-. /  
//                   ___`. .' /--.--\ `. . __  
//                ."" '< `.___\_<|>_/___.' >'"".  
//               | | : `- \`.;`\ _ /`;.`/ - ` : | |  
//                 \ \ `-. \_ __\ /__ _/ .-` / /  
//         ======`-.____`-.___\_____/___.-`____.-'======  
//                            `=---='  
//  
//         .............................................  
//                  佛祖镇楼                  BUG辟易  
//          佛曰:  
//                  写字楼里写字间，写字间里程序员；  
//                  程序人员写程序，又拿程序换酒钱。  
//                  酒醒只在网上坐，酒醉还来网下眠；  
//                  酒醉酒醒日复日，网上网下年复年。  
//                  但愿老死电脑间，不愿鞠躬老板前；  
//                  奔驰宝马贵者趣，公交自行程序员。  
//                  别人笑我忒疯癫，我笑自己命太贱；  
//  


import com.qianfeng.smartplatform.mapper.MenuMapper;
import com.qianfeng.smartplatform.pojo.Menu;
import com.qianfeng.smartplatform.security.handlers.MyAuthenSuccessHandler;
import com.qianfeng.smartplatform.security.handlers.MyLoginFailureHandlder;
import com.qianfeng.smartplatform.security.service.MyUserDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.util.StringUtils;

import java.util.List;

/**
 * Created by Jackiechan on 2022/1/7/11:17
 *
 * @author Jackiechan
 * @version 1.0
 * @sinceon1.0
 */
@EnableWebSecurity //开启spring security
@Configuration
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
    /**
     * 登录: 判断当前的输入的用户的密码和数据库中的密码是否匹配(所有的地址都需要登录吗?)
     * 鉴权:知道当前用户能访问的地址, 当前访问的地址 两个比较就可以  user:add
     * 什么地址不要拦截 或者什么地址需要什么权限
     */

    private MyUserDetailService myUserDetailService;


    private BCryptPasswordEncoder bCryptPasswordEncoder;


    private MyLoginFailureHandlder myLoginFailureHandlder;

    private MyAuthenSuccessHandler myAuthenSuccessHandler;


    private MenuMapper menuMapper;

    @Autowired
    public void setMenuMapper(MenuMapper menuMapper) {
        this.menuMapper = menuMapper;
    }

    @Autowired
    public void setMyAuthenSuccessHandler(MyAuthenSuccessHandler myAuthenSuccessHandler) {
        this.myAuthenSuccessHandler = myAuthenSuccessHandler;
    }

    @Autowired
    public void setMyLoginFailureHandlder(MyLoginFailureHandlder myLoginFailureHandlder) {
        this.myLoginFailureHandlder = myLoginFailureHandlder;
    }

    @Autowired
    public void setbCryptPasswordEncoder(BCryptPasswordEncoder bCryptPasswordEncoder) {
        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
    }

    @Autowired
    public void setMyUserDetailService(MyUserDetailService myUserDetailService) {
        this.myUserDetailService = myUserDetailService;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();//允许跨域
        //查询所有的菜单,遍历设置权限,这样所有的菜单就都设置了权限了
        List<Menu> menuList = menuMapper.selectAllMenu();
        //经过过滤之后我们的数据只保留了有访问地址的那部分,也就是能访问的,需要权限的数据
        menuList.parallelStream().filter(menu-> StringUtils.hasText(menu.getUrl())).forEach(menu -> {
            try {
                //给每个地址设置需要的权限
                http.authorizeRequests().antMatchers(menu.getUrl()).hasAuthority(menu.getPerms());
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
       // super.configure(http);
        http.authorizeRequests()//开始认证琴秋
               // .and().formLogin()
                .and().formLogin().failureHandler(myLoginFailureHandlder)//设置登录失败之后怎么办
                .successHandler(myAuthenSuccessHandler)//自定义成功的处理器
                .loginProcessingUrl("/login")//这个地址实际上是springsecurity处理的,不用我们单独写这个地址
                .permitAll()//放行登录地址
                .and().authorizeRequests().anyRequest()//任意地址
                .authenticated();//需要认证(登录)



    }


    @Override
    public void configure(WebSecurity web) throws Exception {
        //忽略掉不想拦截的地址
        web.ignoring().antMatchers("/index.html", "/css/**", "/js/**", "/websocket/*",
                "/humiture/*");
        super.configure(web);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //告诉spring security 如何根据用户名查询数据以及如何处理密码
        auth.userDetailsService(myUserDetailService).passwordEncoder(bCryptPasswordEncoder);//设置如何通过用户名查询到用户的信息
    }
}
